﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using SGP;

namespace TileEditor
{
    public partial class Form1 : Form
    {
        // Grab the handle to DirectX
        CSGP_Direct3D DX = CSGP_Direct3D.GetInstance();
        // Grab the handle to the Texture Manager
        CSGP_TextureManager TM = CSGP_TextureManager.GetInstance();
        // Set the TileSetPallet to null
        TileSetPallete TSP = null;
        Rectangle selection;
        Point mousePos;
        Point mouseRenderPos;
        Point objectPos;
        Point objectRenderPos;
        Entity[] objectTypes;
        bool setPlayerSpawn;
        int playerSpawnImg;
        int objectSpawnImg;
        bool showNames;
        int collision;
        string workingD;

        public Rectangle Selection
        {
            get { return selection; }
            set { selection = value; }
        }

        private bool looping = true;

        public bool Looping
        {
            get { return looping; }
            set { looping = value; }
        }


        private decimal prevTileW;

        public decimal PrevTileW
        {
            get { return prevTileW; }
            set { prevTileW = value; }
        }

        private decimal prevTileH;

        public decimal PrevTileH
        {
            get { return prevTileH; }
            set { prevTileH = value; }
        }

        Level currLevel;


        public Form1()
        {
            // Initialize the form
            InitializeComponent();
            // Initialize Direct X and Texture Manager
            DX.Initialize(LevelView, true);
            // Add the TileSetPallete to Direct X for rendering
            DX.AddRenderTarget(TileSetView);
            TM.Initialize(DX.Device, DX.Sprite);

            this.TopMost = true;
            string messageBoxText = "Please select your working directory.";
            string caption = "Where are your source files at?";
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            MessageBoxIcon icon = MessageBoxIcon.Exclamation;
            MessageBox.Show(messageBoxText, caption, buttons, icon);

            workingD = "-1";
            while (workingD == "-1")
            {
                if (workingD != "-1")
                    break;
                FolderBrowserDialog findWork = new FolderBrowserDialog();
                if (DialogResult.OK == findWork.ShowDialog())
                {
                    workingD = findWork.SelectedPath.ToString() + "\\";
                    break;
                }
            }




            // Initialize the current level
            currLevel = new Level(1, 1, 1, int.Parse(numericUpDownMapWidth.Value.ToString()), int.Parse(numericUpDownMapHeight.Value.ToString()), int.Parse(numericUpDownTileWidth.Value.ToString()),
                                int.Parse(numericUpDownTileHeight.Value.ToString()));

            currLevel.Groups[0].Color = buttonTriggerColor.BackColor;

            currLevel.TileSets[0].Path = "-1";
            currLevel.TileSets[0].Id = -1;
            currLevel.TileSets[0].SetSize = new Size();

            Size sz = new Size();
            sz.Width = (int)numericUpDownSetSizeWidth.Value;
            sz.Height = (int)numericUpDownSetSizeHeight.Value;
            currLevel.TileSets[0].SetSize = sz;

            for (int w = 0; w < currLevel.MapSize.Width; w++)
            {
                for (int h = 0; h < currLevel.MapSize.Height; h++)
                {
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h] = new Tile();
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h].X = w * currLevel.TileSize.Width;
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h].Y = h * currLevel.TileSize.Height;
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h].SetID = -1;
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h].TileID = -1;
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h].Passable = 1;
                    currLevel.Layers[currLevel.CurrLayer].Map[w, h].TriggerGroup = -1;
                }
            }

            mousePos = new Point();
            mouseRenderPos = new Point();
            objectPos = new Point();
            objectRenderPos = new Point();
            collision = 0;
            prevTileH = numericUpDownTileHeight.Value;
            prevTileW = numericUpDownTileWidth.Value;
            setPlayerSpawn = false;
            showNames = true;

            playerSpawnImg = TM.LoadTexture("playerSpawn.bmp");
            objectSpawnImg = TM.LoadTexture("objectTypes.bmp");
           
            objectTypes = new Entity[1];
            Import("ObjectTypes.xml");
            AdjustLevelScroll();
            ClearSelection();

        }

        public Level GetLevel()
        {
            return currLevel;
        }

        public Rectangle GetSelection()
        {
            return selection;
        }

        public new void Update()
        {
            this.TopMost = false;
        }

        public void Render()
        {
            LevelRender();

            TileSetRender();

            if (TSP != null)
                TSP.Render();


            DX.Resize(LevelView, LevelView.ClientSize.Width, LevelView.ClientSize.Height, true);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Looping = false;
        }

        private void panel1_Resize(object sender, EventArgs e)
        {
            DX.Resize(LevelView, LevelView.ClientSize.Width, LevelView.ClientSize.Height, true);
        }

        private void numericUpDownTileHeight_ValueChanged(object sender, EventArgs e)
        {
            if (numericUpDownTileHeight.Value == 2 || numericUpDownTileHeight.Value == 4 ||
               numericUpDownTileHeight.Value == 8 || numericUpDownTileHeight.Value == 16 ||
               numericUpDownTileHeight.Value == 32 || numericUpDownTileHeight.Value == 64 ||
               numericUpDownTileHeight.Value == 128 || numericUpDownTileHeight.Value == 256)
            {
                prevTileW = numericUpDownTileHeight.Value;
                return;
            }
            if (numericUpDownTileHeight.Value < prevTileW && numericUpDownTileHeight.Value != 2)
            {
                numericUpDownTileHeight.Value = prevTileW / 2;
            }
            else if (numericUpDownTileHeight.Value > prevTileW && numericUpDownTileHeight.Value != 256)
            {
                numericUpDownTileHeight.Value = prevTileW * 2;
            }

            prevTileW = numericUpDownTileHeight.Value;

            currLevel.TileSize = new Size(int.Parse(numericUpDownTileWidth.Value.ToString()),
                                            int.Parse(numericUpDownTileHeight.Value.ToString()));

            for (int i = 0; i < currLevel.Layers.Length; i++)
            {
                for (int w = 0; w < currLevel.MapSize.Width; w++)
                {
                    for (int h = 0; h < currLevel.MapSize.Height; h++)
                    {
                        currLevel.Layers[i].Map[w, h].X = w * currLevel.TileSize.Width;
                        currLevel.Layers[i].Map[w, h].Y = h * currLevel.TileSize.Height;
                    }
                }
            }

            AdjustLevelScroll();

        }

        private void numericUpDownTileWidth_ValueChanged(object sender, EventArgs e)
        {
            if (numericUpDownTileWidth.Value == 2 || numericUpDownTileWidth.Value == 4 ||
                numericUpDownTileWidth.Value == 8 || numericUpDownTileWidth.Value == 16 ||
                numericUpDownTileWidth.Value == 32 || numericUpDownTileWidth.Value == 64 ||
                numericUpDownTileWidth.Value == 128 || numericUpDownTileWidth.Value == 256)
            {
                prevTileW = numericUpDownTileWidth.Value;
                return;
            }
            if (numericUpDownTileWidth.Value < prevTileW && numericUpDownTileWidth.Value != 2)
            {
                numericUpDownTileWidth.Value = prevTileW / 2;
            }
            else if (numericUpDownTileWidth.Value > prevTileW && numericUpDownTileWidth.Value != 256)
            {
                numericUpDownTileWidth.Value = prevTileW * 2;
            }

            prevTileW = numericUpDownTileWidth.Value;

            currLevel.TileSize = new Size(int.Parse(numericUpDownTileWidth.Value.ToString()),
                                            int.Parse(numericUpDownTileHeight.Value.ToString()));

            for (int i = 0; i < currLevel.Layers.Length; i++)
            {
                for (int w = 0; w < currLevel.MapSize.Width; w++)
                {
                    for (int h = 0; h < currLevel.MapSize.Height; h++)
                    {
                        currLevel.Layers[i].Map[w, h].X = w * currLevel.TileSize.Width;
                        currLevel.Layers[i].Map[w, h].Y = h * currLevel.TileSize.Height;
                    }
                }
            }
            AdjustLevelScroll();
        }

        private void numericUpDownMapWidth_ValueChanged(object sender, EventArgs e)
        {
            UpdateMapSize((int)numericUpDownMapWidth.Value, (int)numericUpDownMapHeight.Value);
        }

        private void numericUpDownMapHeight_ValueChanged(object sender, EventArgs e)
        {

            UpdateMapSize((int)numericUpDownMapWidth.Value, (int)numericUpDownMapHeight.Value);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        public void LevelRender()
        {

            DX.Clear(LevelView, Color.White);

            DX.DeviceBegin();
            DX.SpriteBegin();

            Point defaultStart = new Point(0, 0);
            Point offset = Point.Empty;
            offset.X = defaultStart.X + LevelView.AutoScrollPosition.X;
            offset.Y = defaultStart.Y + LevelView.AutoScrollPosition.Y;

            // Iterate trhough all the tiles in the map
            for (int x = (-LevelView.AutoScrollPosition.X - currLevel.TileSize.Width) / currLevel.TileSize.Width; x < (-LevelView.AutoScrollPosition.X + LevelView.Size.Width + currLevel.TileSize.Width) / currLevel.TileSize.Width && x < currLevel.MapSize.Width; x++)
            {
                if (x >= currLevel.MapSize.Width)
                    x = currLevel.MapSize.Width - 1;
                if (x < 0)
                    x = 0;

                for (int y = (-LevelView.AutoScrollPosition.Y - currLevel.TileSize.Height) / currLevel.TileSize.Width; y < (-LevelView.AutoScrollPosition.Y + LevelView.Size.Height + currLevel.TileSize.Height) / currLevel.TileSize.Height && y < currLevel.MapSize.Height; y++)
                {
                    if (y >= currLevel.MapSize.Height)
                        x = currLevel.MapSize.Height - 1;
                    if (y < 0)
                        y = 0;

                    // Calculate where the tile is going to be drawn in the map.
                    Rectangle destRect = Rectangle.Empty;
                    destRect.X = x * currLevel.TileSize.Width + offset.X;
                    destRect.Y = y * currLevel.TileSize.Height + offset.Y;
                    destRect.Size = currLevel.TileSize;

                    // Calculate where the tile is in the bitmap.
                    Rectangle srcRect = Rectangle.Empty;
                    Point p = new Point();
                    if (currLevel.Layers[currLevel.CurrLayer].Map[x, y].SetID != -1 && currLevel.Layers[currLevel.CurrLayer].Map[x, y].TileID != -1)
                    {
                        p.X = currLevel.Layers[currLevel.CurrLayer].Map[x, y].TileID % currLevel.TileSets[currLevel.Layers[currLevel.CurrTileSet].Map[x, y].SetID].SetSize.Width * currLevel.TileSize.Width;
                        p.Y = currLevel.Layers[currLevel.CurrLayer].Map[x, y].TileID / currLevel.TileSets[currLevel.Layers[currLevel.CurrTileSet].Map[x, y].SetID].SetSize.Width * currLevel.TileSize.Height;
                    }
                    srcRect = new Rectangle(p, currLevel.TileSize);

                    // Draw the tile

                    if (currLevel.Layers[currLevel.CurrLayer].Map[x, y].SetID != -1)
                        TM.Draw(currLevel.Layers[currLevel.CurrLayer].Map[x, y].SetID, destRect.X, destRect.Y,
                           1.0f, 1.0f, srcRect, 0.0f, 0.0f, 0.0f, Color.White);

                    // Render Objects, Triggers, or Collision based on tab
                    switch (tabControlToolSet.SelectedIndex)
                    {
                        case 2:
                            if (currLevel.Layers[currLevel.CurrLayer].Map[x, y].TriggerGroup != -1)
                            {
                                Rectangle trigG = new Rectangle(destRect.X + (int)(destRect.Width * (1.0f / 6.0f)), destRect.Y + (int)(destRect.Width * (1.0f / 6.0f)), (int)(destRect.Width * (2.0f / 3.0f)), (int)(destRect.Height * (2.0f / 3.0f)));
                                DX.DrawHollowRect(trigG, currLevel.Groups[currLevel.Layers[currLevel.CurrLayer].Map[x, y].TriggerGroup].Color, 12);
                            }
                            break;
                        case 3:
                            Rectangle scaled = new Rectangle(destRect.X + (int)(destRect.Width * (1.0f / 4)), destRect.Y + (int)(destRect.Height * (1.0f / 4)), destRect.Width / 2, destRect.Height / 2);
                            if (currLevel.Layers[currLevel.CurrLayer].Map[x, y].Passable == 0)
                                DX.DrawRect(scaled, Color.FromArgb(150, 255, 0, 0));
                            else
                                DX.DrawRect(scaled, Color.FromArgb(150, 0, 255, 0));
                            break;
                    }


                    // Draw grid
                    DX.DrawHollowRect(destRect, Color.Black, 1);

                }
            }

            // Render item at cursor based on current tab
            Rectangle spot = new Rectangle(mouseRenderPos, currLevel.TileSize);
            switch (tabControlToolSet.SelectedIndex)
            {
                case 0:
                    if (selection.X != -1 && selection.Y != -1 && selection.Width != -1 && selection.Height != -1)
                    {
                        if (currLevel.TileSets[currLevel.CurrTileSet].Id != -1)
                            TM.Draw(currLevel.TileSets[currLevel.CurrTileSet].Id, spot.X, spot.Y, 1.0f, 1.0f, selection, 0.0f, 0.0f, 0.0f, Color.FromArgb(150, 255, 255, 255));
                    }
                    break;
                case 1:
                    if (currLevel.PlayerSpawn.X != -1 && currLevel.PlayerSpawn.Y != -1)
                        TM.Draw(playerSpawnImg, currLevel.PlayerSpawn.X + LevelView.AutoScrollPosition.X, currLevel.PlayerSpawn.Y + LevelView.AutoScrollPosition.Y);

                    for (int g = 0; g < currLevel.Groups.Length; g++)
                    {
                        if (currLevel.Groups[g].Objects != null)
                            for (int i = 0; i < currLevel.Groups[g].Objects.Length; i++)
                            {
                                int x = currLevel.Groups[g].Objects[i].X;
                                int y = currLevel.Groups[g].Objects[i].Y;
                                if (-LevelView.AutoScrollPosition.X < x && -LevelView.AutoScrollPosition.X + LevelView.Size.Width > x &&
                                    -LevelView.AutoScrollPosition.Y < y && -LevelView.AutoScrollPosition.Y + LevelView.Size.Height > y)
                                {

                                    TM.Draw(objectSpawnImg, x + LevelView.AutoScrollPosition.X, y + LevelView.AutoScrollPosition.Y);
                                    if (listBoxObjectsInWorld.SelectedIndex == i && numericUpDownCurrentGroup.Value == g)
                                        DX.DrawHollowRect(new Rectangle(x + LevelView.AutoScrollPosition.X, y + LevelView.AutoScrollPosition.Y, 32, 32), Color.Yellow, 5);
                                    if (showNames == true)
                                        DX.DrawText(currLevel.Groups[g].Objects[i].Name, x + LevelView.AutoScrollPosition.X, y + LevelView.AutoScrollPosition.Y, Color.Red);
                                }
                            }
                    }

                    if (setPlayerSpawn == true)
                        TM.Draw(playerSpawnImg, objectRenderPos.X, objectRenderPos.Y);
                    else
                        TM.Draw(objectSpawnImg, objectRenderPos.X, objectRenderPos.Y);
                    break;
                case 2:
                    DX.DrawHollowRect(spot, buttonTriggerColor.BackColor, 12);

                    break;
                case 3:
                    if (collision == 0)
                        DX.DrawRect(spot, Color.FromArgb(150, 255, 0, 0));
                    else
                        DX.DrawRect(spot, Color.FromArgb(150, 0, 255, 0));
                    break;
            }
            DX.SpriteEnd();
            DX.DeviceEnd();

            DX.Present();

        }

        // Preview window render function
        public void TileSetRender()
        {
            DX.Clear(TileSetView, Color.Transparent);
            DX.DeviceBegin();
            DX.SpriteBegin();

            if (currLevel.TileSets[currLevel.CurrTileSet].Id != -1)
                TM.Draw(currLevel.TileSets[currLevel.CurrTileSet].Id, 0, 0);

            DX.SpriteEnd();
            DX.DeviceEnd();


            DX.Present();

        }

        // Update the map array when the map size is changed
        public void UpdateMapSize(int width, int height)
        {

            Tile[,] temp = new Tile[width, height];

            for (int l = 0; l < currLevel.Layers.Length; l++)
            {

                for (int w = 0; w < width; w++)
                {
                    for (int h = 0; h < height; h++)
                    {
                        temp[w, h] = new Tile();
                        temp[w, h].X = w * currLevel.TileSize.Width;
                        temp[w, h].Y = h * currLevel.TileSize.Height;
                        temp[w, h].TileID = -1;
                        temp[w, h].SetID = -1;
                        temp[w, h].Passable = 1;
                        temp[w, h].TriggerGroup = -1;
                    }
                }
                for (int w = 0; w < currLevel.MapSize.Width; w++)
                {
                    for (int h = 0; h < currLevel.MapSize.Height; h++)
                    {
                        if (w < width && h < height)
                        {
                            temp[w, h].X = currLevel.Layers[l].Map[w, h].X;
                            temp[w, h].Y = currLevel.Layers[l].Map[w, h].Y;
                            temp[w, h].Passable = currLevel.Layers[l].Map[w, h].Passable;
                            temp[w, h].SetID = currLevel.Layers[l].Map[w, h].SetID;
                            temp[w, h].TileID = currLevel.Layers[l].Map[w, h].TileID;
                            temp[w, h].TriggerGroup = currLevel.Layers[l].Map[w, h].TriggerGroup;
                        }
                    }
                }

                currLevel.Layers[l].Map = new Tile[width, height];

                for (int w = 0; w < width; w++)
                {
                    for (int h = 0; h < height; h++)
                    {
                        currLevel.Layers[l].Map[w, h] = new Tile();
                        currLevel.Layers[l].Map[w, h].X = temp[w, h].X;
                        currLevel.Layers[l].Map[w, h].Y = temp[w, h].Y;
                        currLevel.Layers[l].Map[w, h].Passable = temp[w, h].Passable;
                        currLevel.Layers[l].Map[w, h].SetID = temp[w, h].SetID;
                        currLevel.Layers[l].Map[w, h].TileID = temp[w, h].TileID;
                        currLevel.Layers[l].Map[w, h].TriggerGroup = temp[w, h].TriggerGroup;
                    }
                }
            }

            currLevel.MapSize = new Size(width, height);

            AdjustLevelScroll();
        }

        private void numericUpDownSetSizeWidth_ValueChanged(object sender, EventArgs e)
        {
            currLevel.TileSets[currLevel.CurrTileSet].SetSize = new Size(int.Parse(numericUpDownSetSizeWidth.Value.ToString()),
                                            int.Parse(numericUpDownSetSizeHeight.Value.ToString()));
        }

        private void numericUpDownSetSizeHeight_ValueChanged(object sender, EventArgs e)
        {
            currLevel.TileSets[currLevel.CurrTileSet].SetSize = new Size(int.Parse(numericUpDownSetSizeWidth.Value.ToString()),
                                                        int.Parse(numericUpDownSetSizeHeight.Value.ToString()));
        }

        private void tabControlLayers_SelectedIndexChanged(object sender, EventArgs e)
        {
            currLevel.CurrLayer = tabControlLayers.SelectedIndex;

        }

        private void buttonAddLayer_Click(object sender, EventArgs e)
        {
            string newLayer = "Layer" + (tabControlLayers.TabCount + 1).ToString();
            tabControlLayers.TabPages.Add(newLayer, newLayer);

            Layer[] tempLayers = new Layer[currLevel.Layers.Length];
            for (int i = 0; i < currLevel.Layers.Length; i++)
            {
                tempLayers[i].Map = new Tile[currLevel.MapSize.Width, currLevel.MapSize.Height];
                for (int w = 0; w < currLevel.MapSize.Width; w++)
                {
                    for (int h = 0; h < currLevel.MapSize.Height; h++)
                    {
                        tempLayers[i].Map[w, h] = new Tile(w * currLevel.TileSize.Width, h * currLevel.TileSize.Height, 0, -1, 1, -1);
                    }
                }
                tempLayers[i].Map = currLevel.Layers[i].Map;
            }

            currLevel.Layers = new Layer[currLevel.Layers.Length + 1];

            for (int i = 0; i < currLevel.Layers.Length; i++)
            {
                currLevel.Layers[i].Map = new Tile[currLevel.MapSize.Width, currLevel.MapSize.Height];
                for (int w = 0; w < currLevel.MapSize.Width; w++)
                {
                    for (int h = 0; h < currLevel.MapSize.Height; h++)
                    {
                        currLevel.Layers[i].Map[w, h] = new Tile(w * currLevel.TileSize.Width, h * currLevel.TileSize.Height, 0, -1, 1, -1);
                    }
                }

            }

            for (int i = 0; i < tempLayers.Length; i++)
            {
                currLevel.Layers[i].Map = tempLayers[i].Map;
            }
        }

        private void buttonRemoveLayer_Click(object sender, EventArgs e)
        {
            if (currLevel.Layers.Length > 1)
            {
                tabControlLayers.TabPages.RemoveAt(currLevel.CurrLayer);

                Layer[] tempLayers = new Layer[currLevel.Layers.Length - 1];
                int a = 0;
                for (int i = 0; i < currLevel.Layers.Length; i++)
                {

                    tempLayers[a].Map = new Tile[currLevel.MapSize.Width, currLevel.MapSize.Height];
                    tempLayers[a].Map = currLevel.Layers[i].Map;

                    if (i != currLevel.CurrLayer)
                        a++;
                }

                currLevel.Layers = new Layer[currLevel.Layers.Length - 1];

                for (int i = 0; i < tempLayers.Length; i++)
                {
                    currLevel.Layers[i].Map = tempLayers[i].Map;
                }

                if (currLevel.CurrLayer > currLevel.Layers.Length)
                {
                    currLevel.CurrLayer -= 1;
                }

                for (int i = 0; i < currLevel.Layers.Length; i++)
                {
                    string label = "Layer" + (i + 1).ToString();
                    tabControlLayers.TabPages[i].Text = label;
                }
            }
            else
            {
                string messageBoxText = "You must have at least 1 layer!";
                string caption = "Nope! Chuck Testa!";
                MessageBoxButtons button = MessageBoxButtons.OK;
                MessageBoxIcon icon = MessageBoxIcon.Warning;
                MessageBox.Show(messageBoxText, caption, button, icon);
            }
        }

        private void customizeToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Filter = "Image Files(*.png; *.bmp)|*.png; *.bmp";
                dlg.Multiselect = false;
                dlg.InitialDirectory = workingD;
                if (DialogResult.OK == dlg.ShowDialog())
                {
                    TM.UnloadTexture(playerSpawnImg);
                    TM.UnloadTexture(objectSpawnImg);
                    bool copy = false;
                    string safe = dlg.SafeFileName;
                    for (int i = 0; i < currLevel.TileSets.Length; i++)
                    {
                        if (safe == currLevel.TileSets[i].Path)
                        {
                            copy = true;
                            break;
                        }
                    }

                    if (copy == false)
                    {
                        Bitmap temp;
                        temp = new Bitmap(dlg.OpenFile());

                        if (currLevel.TileSets[0].Id != -1)
                        {
                            TileSet[] tempTS = new TileSet[currLevel.TileSets.Length + 1];

                            for (int i = 0; i < currLevel.TileSets.Length; i++)
                            {
                                tempTS[i] = currLevel.TileSets[i];
                            }

                            currLevel.TileSets = new TileSet[currLevel.TileSets.Length + 1];

                            for (int i = 0; i < currLevel.TileSets.Length; i++)
                            {
                                currLevel.TileSets[i] = tempTS[i];
                            }

                            currLevel.TileSets[currLevel.TileSets.Length - 1].Id = TM.LoadTexture(dlg.FileName.ToString());
                            currLevel.TileSets[currLevel.TileSets.Length - 1].Path = safe;
                            Size setSize = new Size();
                            setSize.Width = temp.Width / currLevel.TileSize.Width;
                            setSize.Height = temp.Height / currLevel.TileSize.Height;
                            currLevel.TileSets[currLevel.TileSets.Length - 1].SetSize = setSize;

                            // Set the current tile set to the newly imported tile set
                            currLevel.CurrTileSet = currLevel.TileSets[currLevel.TileSets.Length - 1].Id;
                        }
                        else
                        {
                            currLevel.TileSets[0].Id = TM.LoadTexture(dlg.FileName.ToString());
                            currLevel.TileSets[0].Path = safe;
                            Size setSize = new Size();
                            setSize.Width = temp.Width / currLevel.TileSize.Width;
                            setSize.Height = temp.Height / currLevel.TileSize.Height;
                            currLevel.TileSets[0].SetSize = setSize;

                            // Set the current tile set to the newly imported tile set
                            currLevel.CurrTileSet = currLevel.TileSets[0].Id;
                        }
                        if (TSP != null)
                        {
                            TSP.Close();
                            buttonShowTileset_Click(sender, e);
                        }
                        playerSpawnImg = TM.LoadTexture("playerSpawn.bmp");
                        objectSpawnImg = TM.LoadTexture("objectTypes.bmp");

                        tabControlToolSet.SelectedIndex = 0;
                    }
                    else
                    {
                        string messageBoxText = "You already have that image loaded!";
                        string caption = "Nope! Chuck Testa!";
                        MessageBoxButtons button = MessageBoxButtons.OK;
                        MessageBoxIcon icon = MessageBoxIcon.Warning;
                        MessageBox.Show(messageBoxText, caption, button, icon);
                    }
                }
            }
            catch
            {
                throw new ApplicationException("Failed to load image!");
            }
        }

        public void AdjustLevelScroll()
        {
            int width = (int)currLevel.MapSize.Width * (int)currLevel.TileSize.Width;
            int height = (int)currLevel.MapSize.Height * (int)currLevel.TileSize.Height;
            LevelView.AutoScrollMinSize = new Size(width, height);

        }

        private void buttonShowTileset_Click(object sender, EventArgs e)
        {
            if (TSP == null)
            {
                TSP = new TileSetPallete(this);
                TSP.FormClosed += tsp_FormClosed;
                TSP.UpdateTileSets();
                TSP.Show(this);
                this.AddOwnedForm(TSP);
            }

        }

        private void tsp_FormClosed(object sender, FormClosedEventArgs e)
        {
            TSP = null;
        }

        public void SetSelectedTileSet(int i)
        {
            currLevel.CurrTileSet = i;
            numericUpDownSetSizeWidth.Value = currLevel.TileSets[currLevel.CurrTileSet].SetSize.Width;
            numericUpDownSetSizeHeight.Value = currLevel.TileSets[currLevel.CurrTileSet].SetSize.Height;
        }

        public void ClearSelection()
        {
            Rectangle clear = new Rectangle(-1, -1, -1, -1);
            selection = new Rectangle();
            selection = clear;
        }

        public void SetSelection(int x, int y, int w, int h)
        {
            Rectangle rect = new Rectangle(x, y, w, h);
            selection = rect;
        }

        public void SetSelection(Rectangle rect)
        {
            selection = rect;
        }

        private void LevelView_MouseMove(object sender, MouseEventArgs e)
        {
            int width = currLevel.TileSize.Width;
            int height = currLevel.TileSize.Height;

            Point defaultStart = e.Location;
            Point offset = Point.Empty;
            offset.X = ((defaultStart.X - LevelView.AutoScrollPosition.X) / width) * width;
            offset.Y = ((defaultStart.Y - LevelView.AutoScrollPosition.Y) / height) * height;
            mouseRenderPos.X = ((defaultStart.X - LevelView.AutoScrollPosition.X) / width) * width + LevelView.AutoScrollPosition.X;
            mouseRenderPos.Y = ((defaultStart.Y - LevelView.AutoScrollPosition.Y) / height) * height + LevelView.AutoScrollPosition.Y;
            mousePos = offset;
            objectPos.X = defaultStart.X - LevelView.AutoScrollPosition.X;
            objectPos.Y = defaultStart.Y - LevelView.AutoScrollPosition.Y;
            objectRenderPos = e.Location;

            if (MouseButtons.Left == e.Button)
                switch (tabControlToolSet.SelectedIndex)
                {
                    // Set the currently selected tiles onto the map in the appropriate tiles
                    case 0:
                        for (int w = 0; w < selection.Width / width; w++)
                        {
                            for (int h = 0; h < selection.Height / height; h++)
                            {

                                if (mousePos.X / width + w < currLevel.MapSize.Width && mousePos.X / width >= 0 && mousePos.Y / height >= 0 && mousePos.Y / height + h < currLevel.MapSize.Height)
                                {
                                    currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width + w, mousePos.Y / height + h].SetID = currLevel.CurrTileSet;
                                    currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width + w, mousePos.Y / height + h].TileID = ((selection.X / width) + w) + (((selection.Y / height) + h) * currLevel.TileSets[currLevel.CurrTileSet].SetSize.Width);
                                }
                            }
                        }
                        break;
                    // Set the current object on the map in the appropriate tile
                    case 1:

                        break;
                    // Add the tile to the current trigger group
                    case 2:
                        if (mousePos.X / width < currLevel.MapSize.Width && mousePos.Y / height < currLevel.MapSize.Height)
                            currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width, mousePos.Y / height].TriggerGroup = (int)numericUpDownTriggerGroup.Value;
                        break;
                    // Set the tiles collision to on/off
                    case 3:
                        if (mousePos.X / width < currLevel.MapSize.Width && mousePos.Y / height < currLevel.MapSize.Height)
                            currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width, mousePos.Y / height].Passable = collision;
                        break;
                    default:
                        break;
                }
        }

        private void LevelView_MouseHover(object sender, EventArgs e)
        {

        }

        private void LevelView_MouseClick(object sender, MouseEventArgs e)
        {
            if (MouseButtons.Left == e.Button)
            {
                int width = currLevel.TileSize.Width;
                int height = currLevel.TileSize.Height;


                switch (tabControlToolSet.SelectedIndex)
                {
                    case 0:
                        for (int w = 0; w < selection.Width / width; w++)
                        {
                            for (int h = 0; h < selection.Height / height; h++)
                            {
                                if (mousePos.X / width + w < currLevel.MapSize.Width && mousePos.Y / height + h < currLevel.MapSize.Height)
                                {
                                    currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width + w, mousePos.Y / height + h].SetID = currLevel.CurrTileSet;
                                    currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width + w, mousePos.Y / height + h].TileID = ((selection.X / width) + w) + (((selection.Y / height) + h) * currLevel.TileSets[currLevel.CurrTileSet].SetSize.Width);
                                }
                            }
                        }
                        break;
                    case 1:
                        if (setPlayerSpawn == true)
                            currLevel.PlayerSpawn = objectPos;
                        else
                        {
                            if (listBoxObjectTypes.SelectedIndex >= 0)
                            {
                                addObjectToGroup(objectPos.X, objectPos.Y, listBoxObjectTypes.SelectedIndex, (int)numericUpDownCurrentGroup.Value);

                            }
                        }
                        break;
                    case 2:
                        if (mousePos.X / width < currLevel.MapSize.Width && mousePos.Y / height < currLevel.MapSize.Height)
                            currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width, mousePos.Y / height].TriggerGroup = (int)numericUpDownTriggerGroup.Value;
                        break;
                    case 3:
                        if (mousePos.X / width < currLevel.MapSize.Width && mousePos.Y / height < currLevel.MapSize.Height)
                            currLevel.Layers[currLevel.CurrLayer].Map[mousePos.X / width, mousePos.Y / height].Passable = collision;
                        break;
                    default:
                        break;
                }

            }
        }

        private void buttonCollisionOn_Click(object sender, EventArgs e)
        {
            collision = 0;
        }

        private void buttonCollisionOff_Click(object sender, EventArgs e)
        {
            collision = 1;
        }

        private void buttonMassCollisionOn_Click(object sender, EventArgs e)
        {
            for (int x = 0; x < currLevel.MapSize.Width; x++)
            {
                for (int y = 0; y < currLevel.MapSize.Height; y++)
                {
                    currLevel.Layers[currLevel.CurrLayer].Map[x, y].Passable = 0;
                }
            }
        }

        private void buttonMassCollisionOff_Click(object sender, EventArgs e)
        {
            for (int x = 0; x < currLevel.MapSize.Width; x++)
            {
                for (int y = 0; y < currLevel.MapSize.Height; y++)
                {
                    currLevel.Layers[currLevel.CurrLayer].Map[x, y].Passable = 1;
                }
            }
        }

        private void buttonTriggerColor_Click(object sender, EventArgs e)
        {
            ColorDialog dlg = new ColorDialog();
            dlg.SolidColorOnly = true;
            dlg.AllowFullOpen = false;
            dlg.ShowDialog(this);

            currLevel.Groups[(int)numericUpDownTriggerGroup.Value].Color = dlg.Color;
            buttonTriggerColor.BackColor = dlg.Color;
        }

        private void numericUpDownTriggerGroup_ValueChanged(object sender, EventArgs e)
        {
            int val = (int)numericUpDownTriggerGroup.Value;
            if (val > currLevel.Groups.Length - 1)
            {
                TriggerGroup[] temp = new TriggerGroup[val + 1];

                for (int i = 0; i < currLevel.Groups.Length; i++)
                {
                    temp[i] = currLevel.Groups[i];
                }

                currLevel.Groups = new TriggerGroup[val + 1];

                for (int i = 0; i < temp.Length; i++)
                {
                    currLevel.Groups[i] = temp[i];
                }

            }

            if (val <= currLevel.Groups.Length - 1)
                buttonTriggerColor.BackColor = currLevel.Groups[val].Color;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            for (int x = 0; x < currLevel.MapSize.Width; x++)
            {
                for (int y = 0; y < currLevel.MapSize.Height; y++)
                {
                    currLevel.Layers[currLevel.CurrLayer].Map[x, y].TriggerGroup = -1;
                }
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            for (int x = 0; x < currLevel.MapSize.Width; x++)
            {
                for (int y = 0; y < currLevel.MapSize.Height; y++)
                {
                    currLevel.Layers[currLevel.CurrLayer].Map[x, y].TriggerGroup = (int)numericUpDownTriggerGroup.Value;
                }
            }
        }

        public void Import(string path)
        {
            XElement xRoot = XElement.Load(path);
            XAttribute xCount = xRoot.Attribute("Count");
            int nCount = Convert.ToInt32(xCount.Value);

            objectTypes = new Entity[nCount];

            IEnumerable<XElement> xEntities = xRoot.Elements();

            listBoxObjectTypes.Items.Clear();

            int i = 0;
            foreach (XElement xEntity in xEntities)
            {
                XAttribute xType = xEntity.Attribute("Type");
                int nType = Convert.ToInt32(xType.Value);

                string sName = xEntity.Value;

                objectTypes[i] = new Entity(nType, sName);

                listBoxObjectTypes.Items.Add(objectTypes[i]);
                i++;
            }
        }
        private void importObjectTypesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Filter = "Object File(*.xml)|*.xml";
                dlg.Multiselect = false;
                dlg.InitialDirectory = workingD;
                if (DialogResult.OK == dlg.ShowDialog())
                {
                    Import(dlg.FileName);
                    tabControlToolSet.SelectedIndex = 1;
                }
                else
                {
                    string messageBoxText = "Improper file format!\nYou didn't load properly!";
                    string caption = "Nope! Chuck Testa!";
                    MessageBoxButtons button = MessageBoxButtons.OK;
                    MessageBoxIcon icon = MessageBoxIcon.Warning;
                    MessageBox.Show(messageBoxText, caption, button, icon);
                }
            }

            catch
            {
                throw new ApplicationException("Invalid object file!");
            }
        }

        private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void newToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            string messageBoxText = "This will erase all current work!\n Are you sure you want to make a new level?";
            string caption = "Are you sure?";
            MessageBoxButtons button = MessageBoxButtons.YesNo;
            MessageBoxIcon icon = MessageBoxIcon.Question;
            if (MessageBox.Show(messageBoxText, caption, button, icon) == DialogResult.Yes)
            {
                currLevel = new Level(1, 1, 1, int.Parse(numericUpDownMapWidth.Value.ToString()), int.Parse(numericUpDownMapHeight.Value.ToString()), int.Parse(numericUpDownTileWidth.Value.ToString()),
                               int.Parse(numericUpDownTileHeight.Value.ToString()));
                currLevel.Groups[0].Color = buttonTriggerColor.BackColor;


                currLevel.TileSets[0].Path = "-1";
                currLevel.TileSets[0].Id = -1;
                currLevel.TileSets[0].SetSize = new Size();

                Size sz = new Size();
                sz.Width = (int)numericUpDownSetSizeWidth.Value;
                sz.Height = (int)numericUpDownSetSizeHeight.Value;
                currLevel.TileSets[0].SetSize = sz;

                for (int w = 0; w < currLevel.MapSize.Width; w++)
                {
                    for (int h = 0; h < currLevel.MapSize.Height; h++)
                    {
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h] = new Tile();
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h].X = w * currLevel.TileSize.Width;
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h].Y = h * currLevel.TileSize.Height;
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h].Passable = 1;
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h].SetID = -1;
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h].TileID = -1;
                        currLevel.Layers[currLevel.CurrLayer].Map[w, h].TriggerGroup = -1;
                    }
                }
                UpdateObjectsInWorldListBox();
            }
        }

        private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
        {

            if (currLevel.PlayerSpawn.X == -1 && currLevel.PlayerSpawn.Y == -1)
            {
                string messageBoxText = "You must assign a spawn point for the player!";
                string caption = "Nope! Chuck Testa!";
                MessageBoxButtons buttons = MessageBoxButtons.OK;
                MessageBoxIcon icon = MessageBoxIcon.Warning;
                MessageBox.Show(messageBoxText, caption, buttons, icon);
                return;
            }

            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            dlg.DefaultExt = "xml";
            dlg.InitialDirectory = workingD;
            try
            {
                if (DialogResult.OK == dlg.ShowDialog())
                {
                    // Create the Level root
                    XElement xRoot = new XElement("Level");

                    // Create the map size element and attach its attributes
                    XElement mapSize = new XElement("MapSize");

                    XAttribute mapW = new XAttribute("width", currLevel.MapSize.Width);
                    mapSize.Add(mapW);

                    XAttribute mapH = new XAttribute("height", currLevel.MapSize.Height);
                    mapSize.Add(mapH);

                    // Attatch the map size
                    xRoot.Add(mapSize);

                    // Create the tile size element and attach its attributes
                    XElement tileSize = new XElement("TileSize");

                    XAttribute tileW = new XAttribute("width", currLevel.TileSize.Width);
                    tileSize.Add(tileW);

                    XAttribute tileH = new XAttribute("height", currLevel.TileSize.Height);
                    tileSize.Add(tileH);

                    // Attach the tile size
                    xRoot.Add(tileSize);

                    // Create the tile set count element and attach its attributes
                    XElement numTS = new XElement("NumberTileSets");
                    xRoot.Add(numTS);

                    XAttribute num = new XAttribute("number", currLevel.TileSets.Length);
                    numTS.Add(num);

                    for (int i = 0; i < currLevel.TileSets.Length; i++)
                    {
                        // Create the tile set image element and attach its attributes
                        XElement tileSet = new XElement("TileSetImage");

                        XAttribute tsW = new XAttribute("width", currLevel.TileSets[i].SetSize.Width);
                        tileSet.Add(tsW);

                        XAttribute tsH = new XAttribute("height", currLevel.TileSets[i].SetSize.Height);
                        tileSet.Add(tsH);

                        XText tsPath = new XText(currLevel.TileSets[i].Path);
                        tileSet.Add(tsPath);

                        // Attach the tile set image
                        xRoot.Add(tileSet);
                    }

                    XElement numLayers = new XElement("NumberLayers");
                    xRoot.Add(numLayers);

                    XAttribute numL = new XAttribute("number", currLevel.Layers.Length);
                    numLayers.Add(numL);

                    // Create and add all tiles from all layers
                    for (int l = 0; l < currLevel.Layers.Length; l++)
                    {
                        XElement L = new XElement("Layer");
                        numLayers.Add(L);
                        for (int x = 0; x < currLevel.MapSize.Width; x++)
                        {
                            for (int y = 0; y < currLevel.MapSize.Height; y++)
                            {
                                XElement xTile = new XElement("Tile");
                                L.Add(xTile);

                                XAttribute xLocX = new XAttribute("XLoc", currLevel.Layers[l].Map[x, y].X);
                                xTile.Add(xLocX);

                                XAttribute xLocY = new XAttribute("YLoc", currLevel.Layers[l].Map[x, y].Y);
                                xTile.Add(xLocY);

                                XAttribute tileID = new XAttribute("TileID", currLevel.Layers[l].Map[x, y].TileID);
                                xTile.Add(tileID);

                                XAttribute setID = new XAttribute("SetID", currLevel.Layers[l].Map[x, y].SetID);
                                xTile.Add(setID);

                                XAttribute passable = new XAttribute("Passable", currLevel.Layers[l].Map[x, y].Passable);
                                xTile.Add(passable);

                                XAttribute trigG = new XAttribute("Trigger", currLevel.Layers[l].Map[x, y].TriggerGroup);
                                xTile.Add(trigG);
                            }
                        }
                    }

                    XElement ps = new XElement("PlayerSpawn");
                    xRoot.Add(ps);

                    XAttribute psX = new XAttribute("XLoc", currLevel.PlayerSpawn.X);
                    ps.Add(psX);

                    XAttribute psY = new XAttribute("YLoc", currLevel.PlayerSpawn.Y);
                    ps.Add(psY);


                    // Create the group containers
                    XElement grp = new XElement("Groups");
                    XAttribute quan = new XAttribute("Quantity", currLevel.Groups.Length);
                    grp.Add(quan);

                    // Add all the enemiess regardless of group
                    xRoot.Add(grp);

                    for (int g = 0; g < currLevel.Groups.Length; g++)
                    {
                        XElement gRP = new XElement("Group");
                        grp.Add(gRP);

                        if (currLevel.Groups[g].Objects != null)
                        {
                            XAttribute quant = new XAttribute("Quantity", currLevel.Groups[g].Objects.Length);
                            gRP.Add(quant);

                            XAttribute clrA = new XAttribute("ColorA", currLevel.Groups[g].Color.A.ToString());
                            gRP.Add(clrA);

                            XAttribute clrR = new XAttribute("ColorR", currLevel.Groups[g].Color.R.ToString());
                            gRP.Add(clrR);

                            XAttribute clrG = new XAttribute("ColorG", currLevel.Groups[g].Color.G.ToString());
                            gRP.Add(clrG);

                            XAttribute clrB = new XAttribute("ColorB", currLevel.Groups[g].Color.B.ToString());
                            gRP.Add(clrB);

                            for (int i = 0; i < currLevel.Groups[g].Objects.Length; i++)
                            {
                                XElement obj = new XElement("Entity");
                                gRP.Add(obj);

                                XAttribute xLocX = new XAttribute("XLoc", currLevel.Groups[g].Objects[i].X);
                                obj.Add(xLocX);

                                XAttribute xLocY = new XAttribute("YLoc", currLevel.Groups[g].Objects[i].Y);
                                obj.Add(xLocY);

                                int typeT = 0;
                                for (int x = 0; x < objectTypes.Length; x++)
                                {
                                    if (objectTypes[x].Name == currLevel.Groups[g].Objects[i].Name)
                                        typeT = objectTypes[x].Type;
                                }

                                XAttribute type = new XAttribute("Type", typeT);
                                obj.Add(type);

                                XAttribute group = new XAttribute("Group", currLevel.Groups[g].Objects[i].Group);
                                obj.Add(group);

                                obj.Value = currLevel.Groups[g].Objects[i].Name;
                            }
                        }
                        else
                        {
                            XAttribute quant = new XAttribute("Quantity", 0);
                            gRP.Add(quant);
                        }
                    }


                    xRoot.Save(dlg.FileName);
                }
            }
            catch
            {
                throw new ApplicationException("Failed to save level!");
            }
        }

        private void openToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Filter = "Object File(*.xml)|*.xml";
                dlg.Multiselect = false;
                dlg.InitialDirectory = workingD;

                if (DialogResult.OK == dlg.ShowDialog())
                {
                    for (int i = 0; i < currLevel.TileSets.Length; i++)
                    {
                        if (currLevel.TileSets[i].Id != -1)
                            TM.UnloadTexture(currLevel.TileSets[i].Id);
                    }

                    TM.UnloadTexture(playerSpawnImg);
                    TM.UnloadTexture(objectSpawnImg);

                    // Find the Level root
                    XElement xRoot = XElement.Load(dlg.FileName);

                    // Find the map size element and get its attributes
                    XElement mapSize = xRoot.Element("MapSize");

                    XAttribute mapW = mapSize.Attribute("width");
                    int mapWidth = Convert.ToInt32(mapW.Value);

                    XAttribute mapH = mapSize.Attribute("height");
                    int mapHeight = Convert.ToInt32(mapH.Value);

                    // Find the tile size element and attach its attributes
                    XElement tileSize = xRoot.Element("TileSize");

                    XAttribute tileW = tileSize.Attribute("width");
                    int tileWidth = Convert.ToInt32(tileW.Value);

                    XAttribute tileH = tileSize.Attribute("height");
                    int tileHeight = Convert.ToInt32(tileH.Value);

                    // Find the tile set count element and get its attributes
                    XElement numTS = xRoot.Element("NumberTileSets");

                    XAttribute num = numTS.Attribute("number");
                    int numTileSets = Convert.ToInt32(num.Value);

                    TileSet[] tileSets = new TileSet[numTileSets];
                    int[] tsWidth = new int[numTileSets];
                    int[] tsHeight = new int[numTileSets];
                    for (int i = 0; i < numTileSets; i++)
                    {
                        // Find the tile set image element and get its attributes
                        XElement tileSet = xRoot.Element("TileSetImage");

                        XAttribute tsW = tileSet.Attribute("width");
                        tsWidth[i] = Convert.ToInt32(tsW.Value);

                        XAttribute tsH = tileSet.Attribute("height");
                        tsHeight[i] = Convert.ToInt32(tsH.Value);

                        tileSets[i].SetSize = new Size(tsWidth[i], tsHeight[i]);

                        tileSets[i].Path = tileSet.Value.ToString();
                    }

                    XElement numLay = xRoot.Element("NumberLayers");

                    XAttribute numL = numLay.Attribute("number");
                    int numLayers = Convert.ToInt32(numL.Value);


                    Layer[] layers = new Layer[numLayers];
                    // Create and add all tiles from all layers
                    int l = 0;
                    layers[l] = new Layer(mapWidth, mapHeight);

                    IEnumerable<XElement> lay = numLay.Elements("Layer");

                    foreach (XElement xLay in lay)
                    {
                        IEnumerable<XElement> xlay = xLay.Elements();
                        int x = 0;
                        int y = 0;
                        foreach (XElement xTile in xlay)
                        {
                            layers[l].Map[x, y] = new Tile();

                            XAttribute xLocX = xTile.Attribute("XLoc");
                            layers[l].Map[x, y].X = Convert.ToInt32(xLocX.Value);

                            XAttribute xLocY = xTile.Attribute("YLoc");
                            layers[l].Map[x, y].Y = Convert.ToInt32(xLocY.Value);

                            XAttribute tileID = xTile.Attribute("TileID");
                            layers[l].Map[x, y].TileID = Convert.ToInt32(tileID.Value);

                            XAttribute setID = xTile.Attribute("SetID");
                            layers[l].Map[x, y].SetID = Convert.ToInt32(setID.Value);

                            XAttribute passable = xTile.Attribute("Passable");
                            layers[l].Map[x, y].Passable = Convert.ToInt32(passable.Value);

                            XAttribute trigG = xTile.Attribute("Trigger");
                            layers[l].Map[x, y].TriggerGroup = Convert.ToInt32(trigG.Value);
                            y++;
                            if (y == mapHeight)
                            {
                                x++;
                                y = 0;
                            }
                        }
                    }

                    XElement plS = xRoot.Element("PlayerSpawn");
                    XAttribute plX = plS.Attribute("XLoc");
                    int playerX = Convert.ToInt32(plX.Value);

                    XAttribute plY = plS.Attribute("YLoc");
                    int playerY = Convert.ToInt32(plY.Value);

                    // Find the group containers
                    XElement grp = xRoot.Element("Groups");
                    XAttribute quan = grp.Attribute("Quantity");
                    int numGrps = Convert.ToInt32(quan.Value);
                    TriggerGroup[] groups = new TriggerGroup[numGrps];

                    IEnumerable<XElement> grP = grp.Elements();
                    int g = 0;
                    foreach (XElement gRP in grP)
                    {
                        XAttribute numObjs = gRP.Attribute("Quantity");
                        if (numObjs != null)
                        {
                            int numObjS = Convert.ToInt32(numObjs.Value);
                            if (numObjS > 0)
                            {
                                XAttribute clrA = gRP.Attribute("ColorA");
                                int CLRa = Convert.ToInt32(clrA.Value);

                                XAttribute clrR = gRP.Attribute("ColorR");
                                int CLRr = Convert.ToInt32(clrR.Value);

                                XAttribute clrG = gRP.Attribute("ColorG");
                                int CLRg = Convert.ToInt32(clrG.Value);

                                XAttribute clrB = gRP.Attribute("ColorB");
                                int CLRb = Convert.ToInt32(clrB.Value);

                                groups[g].Color = Color.FromArgb(CLRa, CLRr, CLRg, CLRb);


                                groups[g].Objects = new Entity[numObjS];
                                IEnumerable<XElement> GRP = gRP.Elements();
                                int i = 0;
                                foreach (XElement obj in GRP)
                                {
                                    XAttribute xLocX = obj.Attribute("XLoc");
                                    groups[g].Objects[i].X = Convert.ToInt32(xLocX.Value);

                                    XAttribute xLocY = obj.Attribute("YLoc");
                                    groups[g].Objects[i].Y = Convert.ToInt32(xLocY.Value);

                                    XAttribute type = obj.Attribute("Type");
                                    for (int k = 0; k < objectTypes.Length; k++)
                                    {
                                        if (Convert.ToInt32(type.Value) == objectTypes[k].Type)
                                        {
                                            groups[g].Objects[i].Type = k;
                                            break;
                                        }
                                    }


                                    XAttribute groupID = obj.Attribute("Group");
                                    groups[g].Objects[i].Group = Convert.ToInt32(groupID.Value);

                                    groups[g].Objects[i].Name = obj.Value.ToString();

                                    i++;
                                }
                            }
                        }
                        g++;
                    }

                    currLevel = new Level(numLayers, numTileSets, numGrps, mapWidth, mapHeight, tileWidth, tileHeight);


                    for (int i = 0; i < numTileSets; i++)
                    {
                        currLevel.TileSets[i].Id = tileSets[i].Id;
                        currLevel.TileSets[i].Path = tileSets[i].Path;
                        if (TM.LoadTexture(workingD + currLevel.TileSets[i].Path) == -1)
                        {
                            string messageBoxText = "Cannot locate " + tileSets[i].Path + "\nPlease relocate this image on your computer";
                            string caption = "Can't find your image!";
                            MessageBoxButtons button = MessageBoxButtons.OK;
                            MessageBoxIcon icon = MessageBoxIcon.Asterisk;
                            MessageBox.Show(messageBoxText, caption, button, icon);

                            OpenFileDialog fixdlg = new OpenFileDialog();
                            fixdlg.Filter = "Image Files(*.png; *.bmp)|*.png; *.bmp";
                            fixdlg.Multiselect = false;
                            fixdlg.InitialDirectory = workingD;
                            if (DialogResult.OK == fixdlg.ShowDialog())
                            {
                                currLevel.TileSets[i].Path = fixdlg.SafeFileName;
                                TM.LoadTexture(fixdlg.FileName);
                            }
                        }
                        currLevel.TileSets[i].SetSize = tileSets[i].SetSize;
                    }

                    playerSpawnImg = TM.LoadTexture("playerSpawn.bmp");
                    objectSpawnImg = TM.LoadTexture("objectTypes.bmp");

                    for (int i = 0; i < numLayers; i++)
                    {
                        currLevel.Layers[i].Map = layers[i].Map;
                        for (int w = 0; w < mapWidth; w++)
                        {
                            for (int h = 0; h < mapHeight; h++)
                            {
                                currLevel.Layers[i].Map[w, h].X = layers[i].Map[w, h].X;
                                currLevel.Layers[i].Map[w, h].Y = layers[i].Map[w, h].Y;
                                currLevel.Layers[i].Map[w, h].TileID = layers[i].Map[w, h].TileID;
                                currLevel.Layers[i].Map[w, h].SetID = layers[i].Map[w, h].SetID;
                                currLevel.Layers[i].Map[w, h].Passable = layers[i].Map[w, h].Passable;
                            }
                        }
                    }

                    for (int i = 0; i < numGrps; i++)
                    {
                        currLevel.Groups[i] = new TriggerGroup();

                        currLevel.Groups[i].Color = groups[i].Color;
                        currLevel.Groups[i].Group = groups[i].Group;
                        if (groups[i].Objects != null)
                        {
                            currLevel.Groups[i].Objects = new Entity[groups[i].Objects.Length];
                            for (int j = 0; j < groups[i].Objects.Length; j++)
                            {
                                currLevel.Groups[i].Objects[j] = groups[i].Objects[j];
                            }
                        }
                    }

                    currLevel.PlayerSpawn = new Point(playerX, playerY);

                    numericUpDownMapWidth.Value = mapWidth;
                    numericUpDownMapHeight.Value = mapHeight;
                    numericUpDownTileWidth.Value = tileWidth;
                    numericUpDownTileHeight.Value = tileHeight;
                    currLevel.CurrLayer = 0;
                    currLevel.CurrTileSet = 0;
                    buttonTriggerColor.BackColor = currLevel.Groups[0].Color;

                    numericUpDownSetSizeWidth.Value = tsWidth[0];
                    numericUpDownSetSizeHeight.Value = tsHeight[0];
                    tabControlToolSet.SelectedIndex = 0;
                    UpdateObjectsInWorldListBox();
                }
            }
            catch
            {
                throw new ApplicationException("Failed to open level!");
            }
        }

        private void helpToolStripButton_Click(object sender, EventArgs e)
        {
            setPlayerSpawn = true;
            tabControlToolSet.SelectedIndex = 1;
            listBoxObjectsInWorld.ClearSelected();
            listBoxObjectTypes.ClearSelected();
        }

        private void listBoxObjectTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxObjectTypes.SelectedIndex >= 0)
            {
                setPlayerSpawn = false;
            }
            else
            {
                if (currLevel.PlayerSpawn.X != -1)
                    numericUpDownObjectX.Value = currLevel.PlayerSpawn.X;
                if (currLevel.PlayerSpawn.Y != -1)
                    numericUpDownObjectY.Value = currLevel.PlayerSpawn.Y;
            }
        }

        private void listBoxObjectsInWorld_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxObjectsInWorld.SelectedIndex != -1)
            {
                buttonObjectRemove.Enabled = true;
                buttonObjectUpdate.Enabled = true;

                setPlayerSpawn = false;
                if (listBoxObjectsInWorld.SelectedIndex != -1)
                {

                    numericUpDownObjectTriggerGroup.Value = currLevel.Groups[(int)numericUpDownCurrentGroup.Value].Objects[(int)listBoxObjectsInWorld.SelectedIndex].Group;
                    numericUpDownObjectX.Value = currLevel.Groups[(int)numericUpDownCurrentGroup.Value].Objects[(int)listBoxObjectsInWorld.SelectedIndex].X;
                    numericUpDownObjectY.Value = currLevel.Groups[(int)numericUpDownCurrentGroup.Value].Objects[(int)listBoxObjectsInWorld.SelectedIndex].Y;
                    listBoxObjectTypes.SelectedIndex = currLevel.Groups[(int)numericUpDownCurrentGroup.Value].Objects[(int)listBoxObjectsInWorld.SelectedIndex].Type;
                }
            }
            else
            {
                if (currLevel.PlayerSpawn.X != -1 && currLevel.PlayerSpawn.Y != -1)
                {
                    numericUpDownObjectX.Value = currLevel.PlayerSpawn.X;
                    numericUpDownObjectY.Value = currLevel.PlayerSpawn.Y;
                }
                buttonObjectRemove.Enabled = false;
                buttonObjectUpdate.Enabled = false;
            }
        }

        private void numericUpDownObjectTriggerGroup_ValueChanged(object sender, EventArgs e)
        {
            int grp = (int)numericUpDownObjectTriggerGroup.Value;
            if (grp >= currLevel.Groups.Length - 1)
            {
                TriggerGroup[] temp = new TriggerGroup[currLevel.Groups.Length + 1];

                for (uint i = 0; i < temp.Length; i++)
                {
                    temp[i] = new TriggerGroup();
                    if (i < currLevel.Groups.Length)
                    {
                        temp[i].Color = currLevel.Groups[i].Color;
                        temp[i].Group = i;
                        if (currLevel.Groups[i].Objects != null)
                        {
                            temp[i].Objects = new Entity[currLevel.Groups[i].Objects.Length];
                            for (uint j = 0; j < currLevel.Groups[i].Objects.Length; j++)
                            {
                                temp[i].Objects[j] = new Entity();
                                temp[i].Objects[j] = currLevel.Groups[i].Objects[j];
                            }
                        }
                    }
                }

                currLevel.Groups = new TriggerGroup[temp.Length];

                for (uint i = 0; i < temp.Length; i++)
                {
                    currLevel.Groups[i] = new TriggerGroup();

                    currLevel.Groups[i].Color = temp[i].Color;
                    currLevel.Groups[i].Group = i;
                    if (temp[i].Objects != null)
                    {
                        currLevel.Groups[i].Objects = new Entity[temp[i].Objects.Length];
                        for (uint j = 0; j < currLevel.Groups[i].Objects.Length; j++)
                        {
                            currLevel.Groups[i].Objects[j] = new Entity();
                            currLevel.Groups[i].Objects[j] = temp[i].Objects[j];
                        }
                    }

                }
            }
        }

        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {
            // Get the group number
            int grp = (int)numericUpDownCurrentGroup.Value;

            // Check if it is higher than the number of groups currently
            if (grp >= currLevel.Groups.Length)
            {
                // Create a new container 1 bigger than the level currently has
                TriggerGroup[] temp = new TriggerGroup[currLevel.Groups.Length + 1];

                // Copy the groups 1 by 1 to the temporary container
                for (uint i = 0; i < temp.Length; i++)
                {
                    // Initialize the group
                    temp[i] = new TriggerGroup();

                    // Make sure you going past the last index of the original container
                    if (i < currLevel.Groups.Length)
                    {
                        // Set the color
                        temp[i].Color = currLevel.Groups[i].Color;
                        // Set the group number
                        temp[i].Group = i;
                        // Initialize the objects to the same size as the group in the original container
                        if (currLevel.Groups[i].Objects != null)
                        {
                            temp[i].Objects = new Entity[currLevel.Groups[i].Objects.Length];
                            if (currLevel.Groups[i].Objects != null)
                            {
                                for (uint j = 0; j < currLevel.Groups[i].Objects.Length; j++)
                                {
                                    temp[i].Objects[j] = new Entity();
                                    temp[i].Objects[j] = currLevel.Groups[i].Objects[j];
                                }
                            }
                        }
                    }
                }

                currLevel.Groups = new TriggerGroup[temp.Length];

                for (uint i = 0; i < temp.Length; i++)
                {
                    currLevel.Groups[i] = new TriggerGroup();

                    currLevel.Groups[i].Color = temp[i].Color;
                    currLevel.Groups[i].Group = i;

                    if (temp[i].Objects != null)
                    {
                        currLevel.Groups[i].Objects = new Entity[temp[i].Objects.Length];
                        for (uint j = 0; j < temp[i].Objects.Length; j++)
                        {
                            currLevel.Groups[i].Objects[j] = new Entity();
                            currLevel.Groups[i].Objects[j] = temp[i].Objects[j];
                        }
                    }
                }
            }

            UpdateObjectsInWorldListBox();
        }

        public void addObjectToGroup(int x, int y, int type, int grp)
        {
            if (currLevel.Groups[grp].Objects == null || currLevel.Groups[grp].Objects[0].Name == "Default")
            {
                currLevel.Groups[grp].Objects = new Entity[1];
                currLevel.Groups[grp].Objects[0].X = x;
                currLevel.Groups[grp].Objects[0].Y = y;
                currLevel.Groups[grp].Objects[0].Type = type;
                currLevel.Groups[grp].Objects[0].Group = grp;
                currLevel.Groups[grp].Objects[0].Name = listBoxObjectTypes.Items[type].ToString();
            }
            else
            {
                Entity[] temp = new Entity[currLevel.Groups[grp].Objects.Length + 1];

                for (int i = 0; i < currLevel.Groups[grp].Objects.Length; i++)
                {
                    temp[i] = currLevel.Groups[grp].Objects[i];
                }

                currLevel.Groups[grp].Objects = new Entity[temp.Length];

                for (int i = 0; i < currLevel.Groups[grp].Objects.Length; i++)
                {
                    currLevel.Groups[grp].Objects[i] = temp[i];
                }

                currLevel.Groups[grp].Objects[currLevel.Groups[grp].Objects.Length - 1].X = x;
                currLevel.Groups[grp].Objects[currLevel.Groups[grp].Objects.Length - 1].Y = y;
                currLevel.Groups[grp].Objects[currLevel.Groups[grp].Objects.Length - 1].Type = type;
                currLevel.Groups[grp].Objects[currLevel.Groups[grp].Objects.Length - 1].Group = grp;
                currLevel.Groups[grp].Objects[currLevel.Groups[grp].Objects.Length - 1].Name = listBoxObjectTypes.Items[type].ToString();
            }

            UpdateObjectsInWorldListBox();
        }

        public void removeObjectFromGroup(int grp, int index)
        {
            if (currLevel.Groups[grp].Objects.Length - 1 > 0)
            {
                Entity[] temp = new Entity[currLevel.Groups[grp].Objects.Length - 1];
                int a = 0;
                for (int i = 0; i < currLevel.Groups[grp].Objects.Length; i++)
                {
                    if (i == index)
                        i++;
                    temp[a] = new Entity();
                    temp[a].Name = currLevel.Groups[grp].Objects[i].Name;
                    temp[a].Group = currLevel.Groups[grp].Objects[i].Group;
                    temp[a].Type = currLevel.Groups[grp].Objects[i].Type;
                    temp[a].X = currLevel.Groups[grp].Objects[i].X;
                    temp[a].Y = currLevel.Groups[grp].Objects[i].Y;
                    a++;
                    if (a == temp.Length)
                        break;
                }

                currLevel.Groups[grp].Objects = new Entity[temp.Length];

                for (int i = 0; i < currLevel.Groups[grp].Objects.Length; i++)
                {
                    currLevel.Groups[grp].Objects[i] = new Entity();
                    currLevel.Groups[grp].Objects[i].Name = temp[i].Name;
                    currLevel.Groups[grp].Objects[i].Group = temp[i].Group;
                    currLevel.Groups[grp].Objects[i].Type = temp[i].Type;
                    currLevel.Groups[grp].Objects[i].X = temp[i].X;
                    currLevel.Groups[grp].Objects[i].Y = temp[i].Y;
                }
            }
            else
            {
                currLevel.Groups[grp].Objects = new Entity[1];
                currLevel.Groups[grp].Objects[0] = new Entity("Default");
            }
            listBoxObjectsInWorld.ClearSelected();
            UpdateObjectsInWorldListBox();
        }

        private void buttonObjectUpdate_Click(object sender, EventArgs e)
        {
            int grp = (int)numericUpDownCurrentGroup.Value;
            int newGrp = (int)numericUpDownObjectTriggerGroup.Value;
            if (listBoxObjectsInWorld.SelectedIndex >= 0 && listBoxObjectTypes.SelectedIndex >= 0)
            {
                if (currLevel.Groups[grp].Objects[listBoxObjectsInWorld.SelectedIndex].Group != (int)numericUpDownObjectTriggerGroup.Value)
                {
                    addObjectToGroup(currLevel.Groups[grp].Objects[listBoxObjectsInWorld.SelectedIndex].X, currLevel.Groups[grp].Objects[listBoxObjectsInWorld.SelectedIndex].Y,
                        currLevel.Groups[grp].Objects[listBoxObjectsInWorld.SelectedIndex].Type, newGrp);

                    removeObjectFromGroup(grp, listBoxObjectsInWorld.SelectedIndex);
                }
                else
                {
                    currLevel.Groups[newGrp].Objects[listBoxObjectsInWorld.SelectedIndex].X = (int)numericUpDownObjectX.Value;
                    currLevel.Groups[newGrp].Objects[listBoxObjectsInWorld.SelectedIndex].Y = (int)numericUpDownObjectY.Value;
                    currLevel.Groups[newGrp].Objects[listBoxObjectsInWorld.SelectedIndex].Type = listBoxObjectTypes.SelectedIndex;
                    currLevel.Groups[newGrp].Objects[listBoxObjectsInWorld.SelectedIndex].Name = listBoxObjectTypes.Items[listBoxObjectTypes.SelectedIndex].ToString();
                }
                UpdateObjectsInWorldListBox();
            }
        }

        public void UpdateObjectsInWorldListBox()
        {
            listBoxObjectsInWorld.ClearSelected();
            listBoxObjectsInWorld.Items.Clear();
            int grp = (int)numericUpDownCurrentGroup.Value;
            if (currLevel.Groups[grp].Objects != null)
            {
                for (int i = 0; i < currLevel.Groups[grp].Objects.Length; i++)
                {
                    if (currLevel.Groups[grp].Objects[i].Name != null)
                        listBoxObjectsInWorld.Items.Add(currLevel.Groups[grp].Objects[i]);
                }
            }
        }

        private void buttonObjectRemove_Click(object sender, EventArgs e)
        {
            removeObjectFromGroup((int)numericUpDownCurrentGroup.Value, listBoxObjectsInWorld.SelectedIndex);
            buttonObjectRemove.Enabled = false;
            buttonObjectUpdate.Enabled = false;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked == true)
                showNames = true;
            else
                showNames = false;
        }

        private void setWorkingDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string messageBoxText = "Please select your working directory.";
            string caption = "Where are your source files at?";
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            MessageBoxIcon icon = MessageBoxIcon.Exclamation;
            MessageBox.Show(messageBoxText, caption, buttons, icon);

            workingD = "-1";
            while (workingD == "-1")
            {
                if (workingD != "-1")
                    break;
                FolderBrowserDialog findWork = new FolderBrowserDialog();
                if (DialogResult.OK == findWork.ShowDialog())
                {
                    workingD = findWork.SelectedPath.ToString() + "\\";
                    break;
                }
            }
        }
    }
}
